<?php
use frontend\modules\yii2\widgets\layouts\markdown\Markdown;
use frontend\modules\yii2\widgets\layouts\example\Example;
use yii\bootstrap\Button;
use yii\bootstrap\Alert;

$this->title = 'Yii2框架源码目录结构详解';
$this->registerMetaTag([
    'name' => 'keywords',
    'content' => 'yii,yii2,框架,目录,结构,教程'
]);
$this->registerMetaTag([
    'name' => 'description',
    'content' => '对Yii2框架源码的各层目录结构进行详细分析'
]);
$this->registerMetaTag([
    'name' => 'author',
    'content' => 'chenzhiwei'
]);

$html = [
    "markdown0" => <<<M0
# Yii2框架源码目录结构详解
下面的就是Yii2框架的源码目录结构，我把它们分为2类，左边是三种不同场景的应用入口目录，右边的是应用的依赖目录：
```shell
yii-advanced
├── frontend           ├── environments
│   ├── assets         │   ├── dev
│   ├── config         │   └── prod
│   ├── controllers    ├── common     
│   ├── models         │   ├── config
│   ├── runtime        │   ├── fixtures 
│   ├── tests          │   ├── mail
│   ├── views          │   ├── models
│   └── web            │   ├── tests
├── backend            │   └── widgets
│   ├── assets         ├── docs
│   ├── config         │   ├── guide
│   ├── controllers    │   ├── guide-es     
│   ├── models         │   ├── guide-fr
│   ├── runtime        │   ├── guide-ja 
│   ├── tests          │   ├── guide-pl
│   ├── views          │   ├── guide-pt-BR
│   └── web            │   └── guide-zh-CN
├── console            ├── vagrant    
│   ├── config         │   ├── config       
│   ├── controllers    │   ├── nginx            
│   ├── migrations     │   └── provision           
│   ├── models         └── vendor       
│   └── runtime                
```
整体来讲Yii2的目录结构是很清晰的，上述目录一共可以分为3类：
- `frontend/backend/console`是应用的入口目录；
- `common`这个目录是上述三个不同应用的公共配置目录；
- `vendor`是存放运行yii的各种依赖的目录；

除了上述3类目录外，可以认为其他的目录都不重要。

> 这个目录只在执行`./init`脚本的时候用到，目的就是把配置文件和入口文件分别放到框架的各个目录。

## frontend
前台的目录，是客户访问的主要应用入口，它的结构如下：
<div class="hidden-xs">
```shell
frontend
├── assets                 // js/css资源管理器                                                   
│   └── AppAsset.php       // 引入yii/bootstrap的js/css                                  
├── config                 // 用于存放配置文件                                  
├── controllers            // 控制器存放目录                                  
│   └── SiteController.php // 这是欢迎页面的控制器                                  
├── models                 // 模型类存放目录                                  
├── tests                  // 测试脚本的存放目录                                  
├── views                  // 视图文件存放目录                                  
│   ├── layouts            // 公共html资源存放目录                                  
│   └── site               // 对应于SiteController的视图                                  
├── web                    // 用户可直接访问的目录                                  
│   ├── assets             // 静态资源存放目录，运行AppAsset的结果                                  
│   ├── css                                                  
│   ├── favicon.ico                                  
│   ├── index.php          // 入口文件                                  
│   ├── index-test.php                                  
│   └── robots.txt         // 避免被谷歌搜索引擎收录                                  
├── codeception.yml        // 测试相关的文件，对应tests目录                                  
├── Dockerfile             // 构建Docker容器的文件                                  
└── runtime                // 日志文件存放目录                                  
```
</div>
<div class="visible-xs">
```shell
frontend
├── assets      // js/css资源管理器                                                   
│   └── AppAsset.php
├── config      // 用于存放配置文件                                  
├── controllers // 控制器存放目录                                                                   
├── models      // 模型类存放目录                                  
├── tests       // 测试脚本的存放目录                                  
├── views       // 视图文件存放目录                                  
│   ├── layouts // 公共html资源存放目录                                  
│   └── site    // SiteController的视图                                  
├── web         // 用户可直接访问的目录                                  
│   ├── assets  // 静态资源存放目录                                
│   ├── css                                       
│   ├── favicon.ico                          
│   ├── index.php   // 入口文件                                  
│   ├── index-tep                             
│   └── robots.txt  // 屏蔽谷歌搜索引擎                                  
├── codeception.php // 测试相关的文件                        
├── Dockerfile  // 构建Docker容器的文件                                  
└── runtime     // 日志文件存放目录                                  
```
</div>

## backend
后台的应用目录，一般给管理员使用。目录结构和功能与frontend是一样的。

## console
控制台应用，主要有下面两个功能：
- 数据库更新
- crontab定时执行YII功能单元

目录结构如下：
```shell
console
├── config      // 配置文件
├── controllers // 控制器目录     
├── migrations  // 数据库变更脚本    
├── models      // 模型类
└── runtime     // 日志类文件 
```

### migrations
这个目录下的文件是数据库变更的历史文件，比如说：给user表新增一个字段`profile`，那应该在这个目录下使用如下命令创建一个新的数据库变更文件：
```shell
yii migrate/create user_add_profile
```
上面的命令会在`console/migrateions`目录下创建一个以`user_add_profile.php`结尾命名的文件，你应该在这个文件中写数据库操作的sql。
运行下面的命令执行数据库变更：
```shell
yii migrate/to user_add_profile
```
上述命令会执行`user_add_profile`里的变更，同时也会把`user_add_profile.php`文件时间戳之前的数据库变更给执行完。

> migrate的使用需要数据库的支持，Yii需要在数据库中存在`migration`表，Yii会把上述执行数据库变更的历史写入到这个表中，作为数据管理的一种手段。


## environments
本目录按照`dev/prod`环境分类存放如下两类的文件：
- 配置文件
- 入口文件

## common
这是存放公共资源的目录，你可以将`frontend/backend/console`都要用到的资源放到这个目录下，其结构如下：
```shell
├── codeception.yml
├── config
├── fixtures
│   └── UserFixture.php
├── mail          // 邮件主体模板目录
│   ├── emailVerify-html.php
│   ├── emailVerify-text.php
│   ├── layouts
│   ├── passwordResetToken-html.php
│   └── passwordResetToken-text.php
├── models         // 公共数据库模型
│   ├── LoginForm.php
│   └── User.php
├── tests
└── widgets        // 用于存放自定义的小部件
    └── Alert.php
```


M0,
];

foreach($html as $name => $item){
    switch ($name) {
        case strpos($name, "example") !== false:
            echo Example::widget($item);
            break;
        case strpos($name, "markdown") !== false:
            echo Markdown::widget(["content" => $item]);
            break;
        default:
            break;
    }
}